﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Drawing;
using DDW.V2D;

namespace DDW.VexTo2DPhysics
{
    public class GenXNA
    {
        public string xmlResult;
        public string path;
        private XmlTextWriter xw;
        private VexTree v2d;
        private List<Body2D> allBodies = new List<Body2D>();
        private List<string> parsedDefs = new List<string>();

        public GenXNA(VexTree v2d, string path, Dictionary<uint, String> paths)
        {
            this.v2d = v2d;
            this.path = path;
            xw = new XmlTextWriter(path, Encoding.UTF8);
            xw.IndentChar = '\t';
            xw.Formatting = Formatting.Indented;
        }


        public void Generate()
        {
            string className = Path.GetFileNameWithoutExtension(path);

            xw.WriteStartDocument();
            xw.WriteComment("generated by SwfNet V2D engine (Swf to Box2D) - http://debreuil.com/v2d");

            xw.WriteStartElement("V2DWorld");
            foreach (string s in v2d.worldData.Keys)
            {
                xw.WriteAttributeString(s, v2d.worldData[s]);
            }

            allBodies.Clear();
            GenBodyList(v2d.root);
            parsedDefs.Clear();

            WriteTextures(xw);
            WriteDefinitions(xw, v2d.root);

            xw.WriteEndElement(); // V2DScreen
            xw.WriteEndDocument();

            xw.Flush();
            xw.Close();

            TextReader tr = new StreamReader(path);
            xmlResult = tr.ReadToEnd();
            tr.Close();
        }

        private void GenBodyList(Body2D b)
        {
            if (!allBodies.Contains(b))
            {
                allBodies.Add(b);
                for (int i = 0; i < b.Children.Count; i++)
                {
                    GenBodyList(b.Children[i]);
                }
            }
        }

        private void WriteTextures(XmlWriter xw)
        {
            List<string> parsed = new List<string>();
            foreach (Body2D b in allBodies)
            {
                if (b.Symbol != null && !parsed.Contains(b.Symbol.SymbolName) && b.Symbol.Path != "")
                {
                    xw.WriteStartElement("V2DTexture");
                    b.Symbol.Dump(xw);
                    parsed.Add(b.Symbol.SymbolName);
                    xw.WriteEndElement(); // V2DTexture
                }
            }
        }

        private void WriteDefinitions(XmlWriter xw, Body2D b)
        {
            for (int i = 0; i < b.Children.Count; i++)
            {
                WriteDefinitions(xw, b.Children[i]);
            }

            if (b.Symbol != null && !parsedDefs.Contains(b.Symbol.SymbolName))
            {
                parsedDefs.Add(b.Symbol.SymbolName);

                xw.WriteStartElement("V2DDefinition");
                xw.WriteAttributeString("Name", b.TypeName);
                xw.WriteAttributeString("LinkageName", b.Symbol.SymbolName);
                xw.WriteAttributeString("OffsetX", b.Bounds.Point.X.ToString());
                xw.WriteAttributeString("OffsetY", b.Bounds.Point.Y.ToString());
                b.DumpShapeData(xw);

                if (b.Children.Count > 0)
                {
                    xw.WriteStartElement("Instances");
                    for (int i = 0; i < b.Children.Count; i++)
                    {
                        WriteInstanceData(xw, b.Children[i]);
                    }
                    xw.WriteEndElement(); // Instances
                }
                if (b.Joints.Count > 0)
                {
                    xw.WriteStartElement("Joints");
                    WriteJointData(xw, b);
                    xw.WriteEndElement(); // Joints
                }

                xw.WriteEndElement(); // V2DDefinition
            }
        }

        private void WriteJointData(XmlWriter xw, Body2D body)
        {
            Joint2D[] jts = new Joint2D[body.Joints.Count];
            body.Joints.Values.CopyTo(jts, 0);
            List<Joint2D> jList = new List<Joint2D>(jts);
            jList.Sort();

            foreach (Joint2D j in jList)
            {
                j.Dump(xw);
            }
        }
        private void WriteInstanceData(XmlWriter xw, Body2D b)
        {
            Dictionary<string, string> dict = null;
            if (v2d.codeData.ContainsKey(b.InstanceName))
            {
                dict = v2d.codeData[b.InstanceName];
            }

            b.DumpInstance(xw, dict);
        }
    }
}
